/* Zatok - язык программирования текстовых игр
 * (С) 2010 - 2012 Меркулов Матвей Юрьевич
 * Код лицензирован под лицензией GNU LGPL
 * Вы можете прочитать текст лицензии по адресу:
 * http://www.gnu.org/copyleft/lesser.html
 * или прочитать русский перевод по адресу:
 * http://ru.wikisource.org/wiki/GNU_Lesser_General_Public_License
 */

package base.function.condition;

import base.CObject;
import base.CProject;
import base.module.CModule;
import java.util.LinkedList;
import parser.CParser;

public class CIf extends CModule {
	private LinkedList<CConditionBlock> Conditions = new LinkedList();

	
	
	private enum ESection { BeforeThen, BetweenThenAndElse, AfterElse }

	
	
	@Override
	public CObject Parse( LinkedList<String> Tokens ) {
		ESection Section = ESection.BeforeThen;
		LinkedList<String> ConditionTokens = new LinkedList<String>();
		LinkedList<String> ThenTokens = new LinkedList<String>();
		LinkedList<String> ElseTokens = new LinkedList<String>();
		for ( String Token : Tokens ) {
			if ( Token.equals( "если" ) ) continue;
			if ( Token.equals( "тогда" ) ) {
				Section = ESection.BetweenThenAndElse;
			} else if ( Token.equals( "иначе" ) ) {
				Section = ESection.AfterElse;
			} else {
				switch( Section ) {
					case BeforeThen:
						ConditionTokens.add( Token );
						break;
					case BetweenThenAndElse:
						ThenTokens.add( Token );
						break;
					case AfterElse:
						ElseTokens.add( Token );
						break;
				}
			}
		}
		
		CIfBlock IfBlock = new CIfBlock();
		IfBlock.Condition = CParser.ParseFunction( ConditionTokens );
		IfBlock.SetFilePosition();
		Conditions.add( IfBlock );

		if ( !ThenTokens.isEmpty() ) {
			// обработка однострочного блока "если Х тогда Y (иначе Z)"
			IfBlock.Modules.add( (CModule) CParser.ParseString( ThenTokens ));
			if ( !ElseTokens.isEmpty() ) {
				CElseBlock ElseBlock = new CElseBlock();
				ElseBlock.Modules.add( (CModule) CParser.ParseString( ElseTokens ));
				Conditions.add( ElseBlock );
			}
			return this;
		}

		LinkedList<CModule> Modules = IfBlock.Modules;
		boolean IsElseBlock = false;
		while (true) {
			Tokens = CParser.ReadTokens();

			if ( Tokens == null ) CParser.Error( "Неожиданный конец файла в блоке \"Если\"" );

			if ( Tokens.getFirst().equals( "конецесли" ) ) break;

			if ( Tokens.getFirst().equals( "иначеесли" ) ) {
				// добавление блока "ИначеЕсли"
				if ( IsElseBlock ) CParser.Error( "\"ИначеЕсли\" после \"Иначе\" в блоке \"Если\"" );
				IfBlock = new CIfBlock();
				Tokens.removeFirst();
				Tokens.removeLast();
				IfBlock.Condition = CParser.ParseFunction( Tokens );
				IfBlock.SetFilePosition();
				Conditions.add( IfBlock );
				Modules = IfBlock.Modules;
			} else if ( Tokens.getFirst().equals( "иначе" ) ) {
				// добавление блока "Иначе"
				if ( IsElseBlock ) CParser.Error( "\"Иначе\" после \"Иначе\" в блоке \"Если\"" );
				CElseBlock ElseBlock = new CElseBlock();
				ElseBlock.SetFilePosition();
				Conditions.add( ElseBlock );
				Modules = ElseBlock.Modules;
				IsElseBlock = true;
			} else {
				CParser.SearchForIllegalKeywords( Tokens, "КонецЕсли" );

				AddModule( Modules, Tokens );
			}
		}
		return this;
	}


	
	@Override
	public void Execute() {
		for ( CConditionBlock Condition : Conditions ) {
			CProject.CurrentLineNumber = Condition.LineNumber;
			CProject.CurrentFileNumber = Condition.FileNumber;
			if ( Condition.IsTrue() ) {
				ExecuteModulesList( Condition.Modules );
				break;
			}
		}
	}
}
